package com.lizemin.builderfactorycase.builer;

import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.Objects;

/**
 * @author lzm
 * @date 2025/10/7 13:46
 * @description 使用建者模式创建不可变的手机类
 */
public class Phone {

    /**
     * 手机品牌(必选)
     */
    private final String brand;

    /**
     * 数量（必选）
     */
    private final int quantity;

    /**
     * 是否需要质保（可选）
     */
    private final boolean needInsurance;

    /**
     * 是否需要手机壳（可选）
     */
    private final boolean needPhoneCase;

    /**
     * 是否需要手机膜（可选）
     */
    private final boolean needScreenProtector;

    private Phone(String brand, int quantity, boolean needInsurance, boolean needPhoneCase, boolean needScreenProtector) {
        this.brand = brand;
        this.quantity = quantity;
        this.needInsurance = needInsurance;
        this.needPhoneCase = needPhoneCase;
        this.needScreenProtector = needScreenProtector;
    }

    public static PhoneBuilder from(String brand, int quantity) {
        return new PhoneBuilder(brand, quantity);
    }

    /**
     * 创建一个手机的副本，并修改其中的某些字段的值
     * @return 一个新的手机对象
     */
    public PhoneBuilder mutate() {
        return new PhoneBuilder(brand, quantity)
                .needInsurance(this.needInsurance)
                .needPhoneCase(this.needPhoneCase)
                .needScreenProtector(this.needScreenProtector);
    }

    /**
     * 手机建造者
     */
    public static class PhoneBuilder {
        /**
         * 手机品牌(必选)
         */
        private String brand;

        /**
         * 数量（必选）
         */
        private int quantity;

        /**
         * 是否需要质保（可选）
         */
        private boolean needInsurance;

        /**
         * 是否需要手机壳（可选）
         */
        private boolean needPhoneCase;

        /**
         * 是否需要手机膜（可选）
         */
        private boolean needScreenProtector;

        /**
         * 创建一个手机对象的建造者, 这里我只留了这一个构造器，是因为这两个参数是必填字段
         * @param brand 手机品牌 必填字段
         * @param quantity 手机数量 必填字段
         */
        public PhoneBuilder(String brand, int quantity) {
            Assert.isTrue(StringUtils.hasText(brand), "手机品牌不能为空");
            Assert.isTrue(quantity > 0, "手机数量不能小于0");
            this.brand = brand;
            this.quantity = quantity;
        }

        public PhoneBuilder quantity(int quantity) {
            Assert.isTrue(quantity > 0, "手机数量不能小于0");
            this.quantity = quantity;
            return this;
        }

        public PhoneBuilder needInsurance(boolean needInsurance) {
            this.needInsurance = needInsurance;
            return this;
        }

        public PhoneBuilder needPhoneCase(boolean needPhoneCase) {
            this.needPhoneCase = needPhoneCase;
            return this;
        }

        public PhoneBuilder needScreenProtector(boolean needScreenProtector) {
            this.needScreenProtector = needScreenProtector;
            return this;
        }

        public Phone build() {
            return new Phone(brand, quantity, needInsurance, needPhoneCase, needScreenProtector);
        }
    }

    // 下面是get方法，注意：创建不可变的对象的类中不需要写set方法
    public String getBrand() {
        return brand;
    }

    public int getQuantity() {
        return quantity;
    }

    public boolean isNeedInsurance() {
        return needInsurance;
    }

    public boolean isNeedPhoneCase() {
        return needPhoneCase;
    }

    public boolean isNeedScreenProtector() {
        return needScreenProtector;
    }

    @Override
    public String toString() {
        return "Phone{" +
                "brand='" + brand + '\'' +
                ", quantity=" + quantity +
                ", needInsurance=" + needInsurance +
                ", needPhoneCase=" + needPhoneCase +
                ", needScreenProtector=" + needScreenProtector +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || getClass() != o.getClass()) return false;
        Phone phone = (Phone) o;
        return quantity == phone.quantity && needInsurance == phone.needInsurance && needPhoneCase == phone.needPhoneCase && needScreenProtector == phone.needScreenProtector && Objects.equals(brand, phone.brand);
    }

    @Override
    public int hashCode() {
        return Objects.hash(brand, quantity, needInsurance, needPhoneCase, needScreenProtector);
    }

}
